home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / des_c.exe / lha / MAIN.C < prev    next >
Text File  |  1990-07-14  |  5KB  |  256 lines

  1. /* Encrypt/decrypt command compatible with Sun's "des" command */
  2. #include <stdio.h>
  3.  
  4. #ifdef __TURBOC__
  5. #include <fcntl.h>
  6. #include <mem.h>
  7. #include <conio.h>
  8. #include <io.h>
  9.  
  10. extern  int     getopt(int, char **, char *);
  11. extern  int     optind, opterr;
  12. extern  char    *optarg, SW;
  13. #else
  14.     extern char *optarg;
  15. #endif
  16.  
  17. char iv[8];    /* Initial vector for CBC mode */
  18. int block;
  19.  
  20. main(argc,argv)
  21. int argc;
  22. char *argv[];
  23. {
  24.     int c,cnt,encrypt,decrypt,hexflag;
  25.     register int i;
  26.     char key[8],tkey1[20],tkey2[20],*akey;
  27. #ifndef __TURBOC__
  28.     char    *getpass();
  29. #endif
  30.  
  31.     hexflag = block = encrypt = decrypt = 0;
  32.     akey = NULL;
  33.     while((c = getopt(argc,argv,"hedk:b")) != EOF){
  34.         switch(c){
  35.         case 'h':
  36.             hexflag++;
  37.             break;
  38.         case 'e':
  39.             encrypt++;
  40.             break;
  41.         case 'd':
  42.             decrypt++;
  43.             break;
  44.         case 'k':
  45.             akey = optarg;
  46.             break;
  47.         case 'b':
  48.             block++;
  49.             break;
  50.         }
  51.     }
  52.     if(encrypt == 0 && decrypt == 0){
  53. #ifdef __TURBOC__
  54.         /* go into \tc\examples\getopt.c and change SW from static */
  55.         /* to global, then move it to this work directory */
  56.         /* It will work with a '-' or '/' option then */
  57.  
  58.         fprintf(stderr,"Usage: des %ce|%cd [%ch] [%ck key] [%cb]\n",
  59.                 SW, SW, SW, SW, SW);
  60. #else
  61.         fprintf(stderr,"Usage: des -e|-d [-h] [-k key] [-b]\n");
  62. #endif
  63.         exit(2);
  64.     }
  65.     if(akey == NULL){
  66. #ifdef __TURBOC__
  67.         int    old_stdin;    /* handle for current stdin   */
  68.         FILE    *new_stdin;    /* input stream for getpass() */
  69.  
  70.         /* save old handle and make sure new one is the console */
  71.  
  72.         old_stdin = dup(fileno(stdin));
  73.         new_stdin = fopen("con", "r");
  74.  
  75.         if (new_stdin == (FILE *)NULL)  {
  76.             fprintf(stderr, "stdin swapping error\n");
  77.             exit(1);
  78.         }
  79.  
  80.         dup2(fileno(new_stdin), 0);        /* 0 for stdin */
  81. #endif
  82.         /* No key on command line, prompt for it */
  83.         memset(tkey1,0,sizeof(tkey1));
  84.         memset(tkey2,0,sizeof(tkey2));
  85.         for(;;){
  86.             akey = getpass("Enter key: ");
  87.             strncpy(tkey1,akey,sizeof(tkey1));
  88.             akey = getpass("Enter key again: ");
  89.             strncpy(tkey2,akey,sizeof(tkey2));
  90.             if(strncmp(tkey1,tkey2,sizeof(tkey1)) != 0){
  91.                 fprintf(stderr,"Key mistyped, try again\n");
  92.             } else
  93.                 break;
  94.         }
  95.         akey = tkey1;
  96. #ifdef __TURBOC__
  97.         /* return to original input */
  98.  
  99.         dup2(old_stdin, 0);        /* 0 for stdin */
  100. #endif
  101.     }
  102.     if(hexflag){
  103.         for(i=0;i<16;i++){
  104.             if(htoa(akey[i]) == -1){
  105.                 fprintf(stderr,"Non-hex character in key\n");
  106.                 exit(1);
  107.             }
  108.         }
  109.         gethex(key,akey,8);
  110.     } else {
  111.         strncpy(key,akey,8);
  112.         /* Set up key, determine parity bit */
  113.         for(cnt = 0; cnt < 8; cnt++){
  114.             c = 0;
  115.             for(i=0;i<7;i++)
  116.                 if(key[cnt] & (1 << i))
  117.                     c++;
  118.             if((c & 1) == 0)
  119.                 key[cnt] |= 0x80;
  120.             else
  121.                 key[cnt] &= ~0x80;
  122.         }
  123.     }
  124.     /* Blot out original key */
  125.     i = strlen(akey);
  126.     i = (i < 8) ? i : 8;
  127.     memset(akey,0,i);
  128.  
  129.     desinit(0);
  130.     setkey(key);
  131.  
  132.     /* Initialize IV to all zeros */
  133.     memset(iv,0,8);
  134.  
  135. #ifdef __TURBOC__
  136.         /*
  137.          *      Change stdin/stdout to binary mode
  138.          */
  139.  
  140.         setmode(0, O_BINARY);
  141.         setmode(1, O_BINARY);
  142. #endif
  143.     if(encrypt){
  144.         doencrypt();
  145.     } else {
  146.         dodecrypt();
  147.     }
  148. }
  149. /* Encrypt standard input to standard output */
  150. doencrypt()
  151. {
  152.     char work[8],*cp,*cp1;
  153.     int cnt,i;
  154.  
  155.     for(;;){
  156.         if((cnt = fread(work,1,8,stdin)) != 8){
  157.             /* Put residual byte count in the last block.
  158.              * Note that garbage is left in the other bytes,
  159.              * if any; this is a feature, not a bug, since it'll
  160.              * be stripped out at decrypt time.
  161.              */
  162.             work[7] = cnt;
  163.         }
  164.         if(!block){
  165.             /* CBC mode; chain in last cipher word */
  166.             cp = work;
  167.             cp1 = iv;
  168.             for(i=8; i!=0; i--)
  169.                 *cp++ ^= *cp1++;
  170.         }
  171.         endes(work);    /* Encrypt block */
  172.         if(!block){    /* Save outgoing ciphertext for chain */
  173.             memcpy(iv,work,8);
  174.         }
  175.         fwrite(work,1,8,stdout);
  176.         if(cnt != 8)
  177.             break;
  178.     }
  179. }
  180. dodecrypt()
  181. {
  182.     char work[8],nwork[8],ivtmp[8],*cp,*cp1;
  183.     int cnt,i;
  184.  
  185.  
  186.     cnt = fread(work,1,8,stdin);    /* Prime the pump */
  187.     for(;;){
  188.         if(!block){    /* Save incoming ciphertext for chain */
  189.             memcpy(ivtmp,work,8);
  190.         }
  191.         dedes(work);
  192.         if(!block){    /* Unchain block, save ciphertext for next */
  193.             cp = work;
  194.             cp1 = iv;
  195.             for(i=8; i!=0; i--){
  196.                 *cp++ ^= *cp1++;
  197.             }
  198.             memcpy(iv,ivtmp,8);
  199.         }
  200.         /* Save buffer pending next read */
  201.         memcpy(nwork,work,8);
  202.         /* Try to read next block */
  203.         cnt = fread(work,1,8,stdin);
  204.         if(cnt != 8){    /* Can "only" be 0 if not 8 */
  205.             /* Prev block was last one, write appropriate number
  206.              * of bytes
  207.              */
  208.             cnt = nwork[7];
  209.             if(cnt < 0 || cnt > 7){
  210.                 fprintf(stderr,"Corrupted file or wrong key\n");
  211.             } else if(cnt != 0)
  212.                 fwrite(nwork,1,cnt,stdout);
  213.             exit(0);
  214.         } else {
  215.             /* Now okay to write previous buffer */
  216.             fwrite(nwork,1,8,stdout);
  217.         }
  218.  
  219.     }
  220. }
  221. /* Convert hex/ascii nybble to binary */
  222. int
  223. htoa(c)
  224. char c;
  225. {
  226.     if(c >= '0' && c <= '9')
  227.         return c - '0';
  228.     if(c >= 'a' && c <= 'f')
  229.         return 10 + c - 'a';
  230.     if(c >= 'A' && c <= 'F')
  231.         return 10 + c - 'A';
  232.     return -1;
  233. }
  234. /* Convert bytes from hex/ascii to binary */
  235. gethex(result,cp,cnt)
  236. register char *result;
  237. register char *cp;
  238. register int cnt;
  239. {
  240.     while(cnt-- != 0){
  241.         *result = htoa(*cp++) << 4;
  242.         *result++ |= htoa(*cp++);
  243.     }
  244. }
  245. #ifdef    DEBUG
  246. put8(cp)
  247. register char *cp;
  248. {
  249.     int i;
  250.  
  251.     for(i=0;i<8;i++){
  252.         fprintf(stderr,"%02x ",*cp++ & 0xff);
  253.     }
  254. }
  255. #endif
  256.